home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume14 / mush6.0 / part08 < prev    next >
Encoding:
Internet Message Format  |  1988-04-12  |  44.1 KB

  1. From: island!argv@sun.com (Dan Heller)
  2. Subject: Mail User's Shell, version 6.0
  3.  
  4. #! /bin/sh
  5. # This is a shell archive.  Remove anything before this line, then unpack
  6. # it by saving it into a file and typing "sh file".  To overwrite existing
  7. # files, type "sh file -c".  You can also feed this as standard input via
  8. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  9. # will see the following message at the end:
  10. #        "End of archive 8 (of 14)."
  11. # Contents:  commands.c mush.h
  12. # Wrapped by rsalz@fig.bbn.com on Wed Apr 13 20:04:50 1988
  13. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  14. if test -f 'commands.c' -a "${1}" != "-c" ; then 
  15.   echo shar: Will not clobber existing file \"'commands.c'\"
  16. else
  17. echo shar: Extracting \"'commands.c'\" \(21317 characters\)
  18. sed "s/^X//" >'commands.c' <<'END_OF_FILE'
  19. X/* @(#)cmds.c    (c) copyright 10/18/86 (Dan Heller) */
  20. X
  21. X#include "mush.h"
  22. X
  23. X/*
  24. X * Note that all of the routines in here act upon and return 0 or -1.
  25. X * if -1, then the main loop will clear message lists.
  26. X */
  27. X
  28. struct cmd cmds[] = {
  29. X#ifdef SIGSTOP
  30. X    { "stop", stop },
  31. X#endif /* SIGSTOP */
  32. X    { "?",       question_mark },{ "sh", sh },
  33. X    { "alias",       do_alias    },  { "unalias",    do_alias   },
  34. X    { "expand",      do_alias    },  { "cmd",     do_alias   },
  35. X    { "uncmd",       do_alias    },  { "from",    do_from    },
  36. X    { "un_hdr",      do_alias    },  { "my_hdr",      do_alias   },
  37. X    { "fkey",       do_alias    },  { "unfkey",     do_alias   },
  38. X    { "set",       set         },  { "unset",     set        },
  39. X    { "ignore",      set         },  { "unignore", set        },
  40. X    { "version",  do_version  },  { "help",    print_help },
  41. X    { "pick",       do_pick     },  { "sort",     sort        },
  42. X    { "next",      readmsg     },  { "previous", readmsg    },
  43. X    { "type",     readmsg     },  { "print",    readmsg    },
  44. X    { "history",  disp_hist   },  { "top",    readmsg       },
  45. X    { "saveopts", save_opts   },  { "source",   source        },
  46. X    { "headers",  do_hdrs     },  { "ls",    ls       },
  47. X    { "folder",   folder      },  { "update",   folder     },
  48. X    { "cd",       cd          },  { "pwd",    cd        },
  49. X    { "exit",      quit        },  { "quit",     quit        },
  50. X    { "write",       save_msg    },  { "save",     save_msg   },
  51. X    { "copy",       save_msg    },  { "folders",  folders    },
  52. X#ifdef CURSES
  53. X    { "curses",   curses_init },  { "bind", bind_it   }, { "unbind", bind_it },
  54. X#endif /* CURSES */
  55. X    { "preserve", preserve    },  { "unpreserve",  preserve   },
  56. X    { "replyall", respond     },  { "replysender", respond    },
  57. X    { "delete",      delete      },  { "undelete",    delete     },
  58. X    { "mail",       do_mail     },  { "echo",       do_echo    },
  59. X    { "lpr",      lpr          },  { "alternates",  alts       },
  60. X    { NULL, quit }
  61. X};
  62. X
  63. struct cmd ucb_cmds[] = {
  64. X    { "t",   readmsg   }, { "n",  readmsg  }, { "p", readmsg  },
  65. X    { "+",   readmsg   }, { "-",  readmsg  }, { "P", readmsg  },
  66. X    { "Print", readmsg }, { "T",  readmsg  }, { "Type", readmsg },
  67. X    { "x",   quit      }, { "xit", quit    }, { "q",  quit    },
  68. X    { ":a",  do_hdrs   }, { ":d", do_hdrs  }, { ":r", do_hdrs },
  69. X    { ":o",  do_hdrs   }, { ":u", do_hdrs  }, { ":n", do_hdrs },
  70. X    { "z",   do_hdrs   }, { "z-", do_hdrs  }, { "z+", do_hdrs },
  71. X    { "h",   do_hdrs   }, { "H",  do_hdrs  },
  72. X    { "f",   do_from   }, { "m",  do_mail  }, { "alts", alts  },
  73. X    { "d",   delete    }, { "dt", delete   }, { "dp", delete  },
  74. X    { "u",   delete    }, { "fo", folder   },
  75. X    { "s",   save_msg  }, { "co", save_msg }, { "w", save_msg },
  76. X    { "pre", preserve  }, { "unpre", preserve },
  77. X    { "R",   respond   }, { "r",   respond },
  78. X    { "reply", respond }, { "respond", respond },
  79. X    { NULL, quit }
  80. X};
  81. X
  82. struct cmd hidden_cmds[] = {
  83. X    { "debug", toggle_debug }, { "open",     nopenfiles },
  84. X    { "flags", msg_flags    }, { "stty",    my_stty    },
  85. X    { "setenv",    Setenv      }, { "unsetenv",     Unsetenv   },
  86. X    { "printenv", Printenv  },
  87. X    { NULL, quit }
  88. X};
  89. X
  90. toggle_debug(argc, argv)
  91. char **argv;
  92. X{
  93. X    if (argc < 2) /* no value -- toggle "debug" (off/on) */
  94. X    debug = !debug;
  95. X    else
  96. X    debug = atoi(*++argv);
  97. X    print("debugging value: %d\n", debug);
  98. X    return -1;
  99. X}
  100. X
  101. X/* if + was specified, then print messages without headers.
  102. X * n or \n (which will be NULL) will print next unread or undeleted message.
  103. X */
  104. readmsg(x, argv, list)
  105. register char **argv, list[];
  106. X{
  107. X    register char *p = x? *argv : NULL;
  108. X    register long flg = 0;
  109. X    extern FILE *ed_fp;
  110. X
  111. X    if (x && *++argv && !strcmp(*argv, "-?"))
  112. X    return help(0, "readmsg", cmd_help);
  113. X    /* View a message as long as user isn't in the editor.  If is_getting
  114. X     * is set, then the user is typing in a letter (or something else not
  115. X     * threatening in tool mode).  If ed_fp is not null, then we've got the
  116. X     * file open for typing.  If it's NULL, then an editor is going.
  117. X     */
  118. X    if (ison(glob_flags, IS_GETTING) && !ed_fp) {
  119. X    print("Not while you're in the editor, you don't.\n");
  120. X    return -1;
  121. X    }
  122. X    if (!msg_cnt) {
  123. X    print("No messages.\n");
  124. X    return -1;
  125. X    }
  126. X    if (x)
  127. X    if (!strcmp(p, "top"))
  128. X        turnon(flg, TOP);
  129. X    else if (*p == '+') {
  130. X        turnon(flg, NO_PAGE);
  131. X        turnon(flg, NO_HEADER);
  132. X    } else if (isupper(*p))
  133. X        turnon(flg, NO_IGNORE);
  134. X
  135. X    if (x && (x = get_msg_list(argv, list)) == -1)
  136. X    return -1;
  137. X    else if (x == 0) {  /* no arguments were parsed (or given) */
  138. X    /* get_msg_list sets current msg on */
  139. X    unset_msg_bit(list, current_msg);
  140. X    /* most commands move to the "next" message. type and print don't */
  141. X    if ((!p || !*p || *p == 'n' || *p == '+') && current_msg < msg_cnt &&
  142. X                    isoff(msg[current_msg].m_flags, UNREAD))
  143. X        current_msg++;
  144. X    if (p && (*p == '-' || !strcmp(p, "previous"))) {
  145. X        while (--current_msg >= 0 && ison(msg[current_msg].m_flags, DELETE))
  146. X        ;
  147. X        if (current_msg < 0) {
  148. X        print("No previous message.\n");
  149. X        current_msg = 0;
  150. X        return -1;
  151. X        }
  152. X    } else {
  153. X        /*
  154. X         * To be compatible with ucb-mail, find the next available unread
  155. X         * message.  If at the end, only wrap around if "wrap" is set.
  156. X         */
  157. X        if (current_msg == msg_cnt && do_set(set_options, "wrap"))
  158. X        current_msg = 0;
  159. X        /* "type" or "print" prints the current only -- "next" goes on.. */
  160. X        if (!p || !*p || *p == 'n')
  161. X        while (current_msg < msg_cnt &&
  162. X            ison(msg[current_msg].m_flags, DELETE))
  163. X            current_msg++;
  164. X        if (current_msg >= msg_cnt) {
  165. X        print("No more messages.\n");
  166. X        current_msg = msg_cnt - 1;
  167. X        return -1;
  168. X        }
  169. X    }
  170. X    set_msg_bit(list, current_msg);
  171. X    }
  172. X    /* If we're piping messages, just return the message list */
  173. X    if (ison(glob_flags, DO_PIPE))
  174. X    return 0;
  175. X    current_msg = 0;
  176. X    for (x = 0; x < msg_cnt; x++)
  177. X    if (msg_bit(list, x)) {
  178. X        current_msg = x;
  179. X#ifdef SUNTOOL
  180. X        if (istool > 1) {
  181. X        read_mail(NO_ITEM, 0, NO_EVENT);
  182. X        return 0;
  183. X        }
  184. X#endif /* SUNTOOL */
  185. X        display_msg(x, flg);
  186. X    }
  187. X    return 0;
  188. X}
  189. X
  190. preserve(n, argv, list)
  191. register int n;        /* no use for argc, so use space for a local variable */
  192. register char **argv, list[];
  193. X{
  194. X    register int unpre;
  195. X
  196. X    unpre = !strncmp(*argv, "un", 2);
  197. X    if (*++argv && !strcmp(*argv, "-?"))
  198. X    return help(0, "preserve_help", cmd_help);
  199. X    if (get_msg_list(argv, list) == -1)
  200. X    return -1;
  201. X    for (n = 0; n < msg_cnt; n++)
  202. X    if (msg_bit(list, n))
  203. X        if (unpre) {
  204. X        if (ison(msg[n].m_flags, PRESERVE)) {
  205. X            turnoff(msg[n].m_flags, PRESERVE);
  206. X            turnon(glob_flags, DO_UPDATE);
  207. X        }
  208. X        } else {
  209. X        if (isoff(msg[n].m_flags, PRESERVE) ||
  210. X            ison(msg[n].m_flags, DELETE)) {
  211. X            turnon(msg[n].m_flags, PRESERVE);
  212. X            turnon(glob_flags, DO_UPDATE);
  213. X            turnoff(msg[n].m_flags, DELETE);
  214. X        }
  215. X        }
  216. X    if (istool)
  217. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  218. X    return 0;
  219. X}
  220. X
  221. lpr(n, argv, list)
  222. register int n;  /* no use for argc, so use its address space for a variable */
  223. register char **argv, list[];
  224. X{
  225. X    register FILE    *pp;
  226. X    register long     flags = 0;
  227. X    char        print_cmd[128], *printer, c, *cmd;
  228. X    int            total = 0, (*oldint)(), (*oldquit)();
  229. X
  230. X    turnon(flags, NO_IGNORE);
  231. X    if (!(printer = do_set(set_options, "printer")) || !*printer)
  232. X    printer = DEF_PRINTER;
  233. X    while (argv && *++argv && **argv == '-') {
  234. X    n = 1;
  235. X    while (c = argv[0][n++])
  236. X        switch(c) {
  237. X        case 'n': turnon(flags, NO_HEADER);
  238. X        when 'h': turnoff(flags, NO_IGNORE);
  239. X        when 'P': case 'd':
  240. X            if (!argv[0][n]) {
  241. X                print("specify printer!\n");
  242. X                return -1;
  243. X            }
  244. X            printer = argv[0] + n;
  245. X            n += strlen(printer);
  246. X        otherwise: return help(0, "lpr", cmd_help);
  247. X        }
  248. X    }
  249. X    if (get_msg_list(argv, list) == -1)
  250. X    return -1;
  251. X
  252. X    if (cmd = do_set(set_options, "print_cmd"))
  253. X    (void) strcpy(print_cmd, cmd);
  254. X    else
  255. X#ifdef SYSV
  256. X    (void) sprintf(print_cmd, "%s -d%s", LPR, printer);
  257. X#else
  258. X    (void) sprintf(print_cmd, "%s -P%s", LPR, printer);
  259. X#endif /* SYSV */
  260. X    Debug("print command: %s\n", print_cmd);
  261. X    if (!(pp = popen(print_cmd, "w"))) {
  262. X    error("cannot print");
  263. X    return -1;
  264. X    }
  265. X    on_intr();
  266. X    for (n = 0; isoff(glob_flags, WAS_INTR) && n < msg_cnt; n++) {
  267. X    if (msg_bit(list, n)) {
  268. X        if (total++)
  269. X        fputc('\f', pp); /* send a formfeed for multiple copies */
  270. X        print("printing message %d...", n+1);
  271. X        print_more("(%d lines)\n", copy_msg(n, pp, flags));
  272. X    }
  273. X    }
  274. X    off_intr();
  275. X    (void) pclose(pp);
  276. X    print_more("%d message%s printed ", total, (total==1)? "": "s");
  277. X    if (cmd)
  278. X    print_more("through \"%s\".\n", cmd);
  279. X    else
  280. X    print_more("at \"%s\".\n", printer);
  281. X    return 0;
  282. X}
  283. X
  284. X/* save [msg_list] [file] */
  285. save_msg(n, argv, list)   /* argc isn't used, so use space for variable 'n' */
  286. register char **argv, list[];
  287. X{
  288. X    register FILE    *mail_fp;
  289. X    register char     *file = NULL, *mode, firstchar = **argv, *tmp;
  290. X    int         msg_number, force;
  291. X    long         flg = 0;
  292. X
  293. X    if (*++argv && !strcmp(*argv, "-?"))
  294. X    return help(0, "save_help", cmd_help);
  295. X    if (force = (*argv && !strcmp(*argv, "!")))
  296. X    argv++;
  297. X    if ((n = get_msg_list(argv, list)) == -1)
  298. X    return -1;
  299. X    argv += n;
  300. X    if (*argv && *(file = *argv) == '\\')
  301. X    file++;
  302. X    else if (!file) {
  303. X    /* if no filename specified, save in ~/mbox */
  304. X    if (firstchar == 'w') {
  305. X        /* mbox should have headers. If he really wants it, specify it */
  306. X        print("Must specify file name for 'w'\n");
  307. X        return -1;
  308. X    }
  309. X    if (!(file = do_set(set_options, "mbox")) || !*file)
  310. X        file = DEF_MBOX;
  311. X    }
  312. X    n = 1; /* tell getpath to ignore no such file or directory */
  313. X    tmp = getpath(file, &n);
  314. X    if (n < 0) {
  315. X    print("%s: %s\n", file, tmp);
  316. X    return -1;
  317. X    } else if (n) {
  318. X    print("%s is a directory\n", file);
  319. X    return -1;
  320. X    }
  321. X    file = tmp;
  322. X    if (force || Access(file, F_OK))
  323. X    mode = "w", force = 0;
  324. X    else
  325. X    mode = "a";
  326. X
  327. X    if (!(mail_fp = fopen(file, mode))) {
  328. X    error("cannot save in \"%s\"", file);
  329. X    return -1;
  330. X    }
  331. X#ifdef SUNTOOL
  332. X    if (istool)
  333. X    lock_cursors();
  334. X#endif /* SUNTOOL */
  335. X    turnon(flg, NO_IGNORE);
  336. X    if (firstchar == 'w')
  337. X    turnon(flg, NO_HEADER);
  338. X    else
  339. X    turnon(flg, UPDATE_STATUS);
  340. X    if (do_set(set_options, "keepsave"))
  341. X    firstchar = 'c';
  342. X    for (n = msg_number = 0; msg_number < msg_cnt; msg_number++)
  343. X    if (msg_bit(list, msg_number)) {
  344. X            print("%sing msg %d... ",
  345. X        (firstchar == 's')? "Sav" : "Writ", msg_number+1);
  346. X        print_more("(%d lines)\n", copy_msg(msg_number, mail_fp, flg));
  347. X        /* only mark "deleted" if mailfile is /usr/spool/mail and
  348. X         * we're not "copying.  If keepsave is set, then firstchar
  349. X         * will have already been changed to 'c'
  350. X         */
  351. X        if (!strcmp(mailfile, spoolfile) && firstchar != 'c' &&
  352. X        isoff(glob_flags, READ_ONLY))
  353. X        turnon(msg[msg_number].m_flags, DELETE);
  354. X        n++;
  355. X    }
  356. X    fclose(mail_fp);
  357. X    print_more("%s %d msg%s to %s\n",
  358. X        (*mode == 'a')? "Appended" : "Saved", n, (n != 1)? "s": "", file);
  359. X    if (!strcmp(mailfile, spoolfile))
  360. X    turnon(glob_flags, DO_UPDATE);
  361. X#ifdef SUNTOOL
  362. X    if (istool) {
  363. X    unlock_cursors();
  364. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  365. X    add_folder_to_menu(folder_item, 3);
  366. X    add_folder_to_menu(save_item, 1);
  367. X    }
  368. X#endif /* SUNTOOL */
  369. X    return 0;
  370. X}
  371. X
  372. respond(n, argv, list)
  373. register int n;  /* no use for argc, so use its address space for a variable */
  374. register char **argv, *list;
  375. X{
  376. X    register char *cmd = *argv;
  377. X    char list1[MAXMSGS_BITS];
  378. X
  379. X    if (*++argv && !strcmp(*argv, "-?"))
  380. X    return help(0, "respond_help", cmd_help);
  381. X    if ((n = get_msg_list(argv, list)) == -1)
  382. X    return -1;
  383. X    /* make into our own list so ~: commands don't overwrite this list */
  384. X    bitput(list, list1, MAXMSGS, =);
  385. X    /* back up one arg to replace "cmd" in the new argv[0] */
  386. X    argv += (n-1);
  387. X    if (!strcmp(cmd, "replyall"))
  388. X    Upper(*cmd);
  389. X    strdup(argv[0], cmd);
  390. X    current_msg = -1;
  391. X    for (n = 0; n < msg_cnt; n++)
  392. X    if (msg_bit(list1, n)) {
  393. X        if (current_msg > -1 && istool) {
  394. X        print("tool mode can not respond to multiple messages.");
  395. X        continue;
  396. X        }
  397. X        current_msg = n;
  398. X        set_isread(n);
  399. X        if (do_mail(1 /* ignored */, argv, list) == -1)
  400. X        return -1;
  401. X        set_replied(n); /* only if mail got delivered */
  402. X#ifdef SUNTOOL
  403. X        if (istool)
  404. X        do_hdrs(0, DUBL_NULL, NULL);
  405. X#endif /* SUNTOOL */
  406. X    }
  407. X    return 0;
  408. X}
  409. X
  410. X/* cd to a particular directory specified by "p" */
  411. cd(x, argv) /* argc, unused -- use space for a non-register variable */
  412. register char **argv;
  413. X{
  414. X    char cwd[MAXPATHLEN], buf[MAXPATHLEN];
  415. X    register char *path, *p = argv[1], *cdpath = NULL, *p2;
  416. X#ifdef SYSV
  417. X    char *getcwd();
  418. X#else
  419. X    char *getwd();
  420. X#endif /* SYSV */
  421. X    int err = 0;
  422. X
  423. X    if (!strcmp(*argv, "pwd") && (p = do_set(set_options, "cwd")) && *p) {
  424. X    print("%s\n", p);
  425. X    return -1;
  426. X    }
  427. X    if (!p || !*p) /* if no args, pwd = ".", cd = ~ */
  428. X    p = (**argv == 'p')? "." : "~";
  429. X    /* if a full path was not specified, loop thru cdpath */
  430. X    if (**argv != 'p' && *p != '/' && *p != '~' && *p != '+')
  431. X    cdpath = do_set(set_options, "cdpath");
  432. X    do  {
  433. X    if (cdpath) {
  434. X        char c;
  435. X        if (p2 = any(cdpath, " \t"))
  436. X        c = *p2, *p2 = 0;
  437. X        (void) sprintf(buf, "%s/%s", cdpath, p);
  438. X        if (cdpath = p2) /* assign and compare to NULL */
  439. X        *p2 = c;
  440. X        while (cdpath && isspace(*cdpath))
  441. X        cdpath++;
  442. X    } else
  443. X        (void) strcpy(buf, p);
  444. X    x = 0;
  445. X    path = getpath(buf, &x);
  446. X    if (x != 1 || chdir(path) == -1)
  447. X        err = errno;
  448. X    else
  449. X        err = 0;
  450. X    } while (err && cdpath && *cdpath);
  451. X    if (err)
  452. X    error(p);
  453. X#ifdef SYSV
  454. X    if (getcwd(cwd, 128) == NULL)
  455. X#else
  456. X    if (getwd(cwd) == NULL)
  457. X#endif /* SYSV */
  458. X    print("can't get cwd: %s.\n", cwd), err++;
  459. X    else {
  460. X    char **new_argv;
  461. X    (void) sprintf(buf, "set cwd = \"%s\"", cwd);
  462. X    Debug("%s\n", buf);
  463. X    if (new_argv = mk_argv(buf, &x, 1))
  464. X        (void) add_option(&set_options, new_argv), free_vec(new_argv);
  465. X    }
  466. X    if (istool || iscurses || err) {
  467. X    if (err)
  468. X        turnon(glob_flags, CONT_PRNT);
  469. X    print("Working dir: %s\n", cwd);
  470. X    }
  471. X    return -1;
  472. X}
  473. X
  474. quit(argc, argv)
  475. char **argv;
  476. X{
  477. X    u_long updated = ison(glob_flags, DO_UPDATE);
  478. X
  479. X    if (argc > 1 && !strcmp(argv[1], "-?"))
  480. X    return help(0, "quit_help", cmd_help);
  481. X    if ((!argc || (*argv && **argv == 'q')) && ison(glob_flags, DO_UPDATE)
  482. X    && !copyback())
  483. X    return -1;
  484. X#ifdef CURSES
  485. X    if (iscurses) {
  486. X    /* we may already be on the bottom line; some cases won't be */
  487. X    move(LINES-1, 0), refresh();
  488. X    if (updated)
  489. X        putchar('\n');
  490. X    }
  491. X#endif /* CURSES */
  492. X    cleanup(0);
  493. X#ifdef lint
  494. X    return 0;
  495. X#endif /* lint */
  496. X}
  497. X
  498. delete(argc, argv, list)
  499. register int argc;
  500. register char **argv, list[];
  501. X{
  502. X    register int prnt_next, undel = argc && **argv == 'u';
  503. X    int old_msg = current_msg;
  504. X
  505. X    prnt_next = (argv && (!strcmp(*argv, "dt") || !strcmp(*argv, "dp")));
  506. X
  507. X    if (argc && *++argv && !strcmp(*argv, "-?")) {
  508. X    print("usage: delete/undelete [msg_list]\n");
  509. X    return -1;
  510. X    }
  511. X
  512. X    if (ison(glob_flags, READ_ONLY)) {
  513. X    print("Folder is read-only\n");
  514. X    return -1;
  515. X    }
  516. X
  517. X    if (get_msg_list(argv, list) == -1)
  518. X    return -1;
  519. X    for (argc = 0; argc < msg_cnt; argc++)
  520. X    if (msg_bit(list, argc))
  521. X        if (undel)
  522. X        turnoff(msg[argc].m_flags, DELETE);
  523. X        else
  524. X        turnon(msg[argc].m_flags, DELETE);
  525. X
  526. X    /* only if current_msg has been affected && not in curses mode */
  527. X    if (prnt_next == 0 && !iscurses && msg_bit(list, current_msg))
  528. X    prnt_next = !!do_set(set_options, "autoprint"); /* change to boolean */
  529. X
  530. X    turnon(glob_flags, DO_UPDATE);
  531. X
  532. X    /* goto next available message if current was just deleted.
  533. X     * If there are no more messages, turnoff prnt_next.
  534. X     */
  535. X    if (!iscurses && !undel && ison(msg[current_msg].m_flags, DELETE))
  536. X    next_msg();
  537. X
  538. X    if (prnt_next && !undel && !iscurses)
  539. X    if (old_msg != current_msg && isoff(msg[current_msg].m_flags, DELETE))
  540. X        display_msg(current_msg, (long)0);
  541. X    else
  542. X        print("No more messages.\n"), current_msg = old_msg;
  543. X#ifdef SUNTOOL
  544. X    if (istool)
  545. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  546. X#endif /* SUNTOOL */
  547. X    return 0;
  548. X}
  549. X
  550. X/*
  551. X * historically from the "from" command in ucb-mail, this just prints
  552. X * the composed header of the messages set in list or in pipe.
  553. X */
  554. do_from(n, argv, list)
  555. char **argv, list[];
  556. X{
  557. X    int inc_cur_msg = 0;
  558. X
  559. X    if (argv && *++argv && !strcmp(*argv, "-?"))
  560. X    return help(0, "from", cmd_help);
  561. X    if (argv && *argv && (!strcmp(*argv, "+") || !strcmp(*argv, "-")))
  562. X    if (!strcmp(*argv, "+")) {
  563. X        if (!*++argv && current_msg < msg_cnt-1)
  564. X        current_msg++;
  565. X        inc_cur_msg = 1;
  566. X    } else if (!strcmp(*argv, "-")) {
  567. X        if (!*++argv && current_msg > 0)
  568. X        current_msg--;
  569. X        inc_cur_msg = -1;
  570. X    }
  571. X    if (get_msg_list(argv, list) == -1)
  572. X    return -1;
  573. X    for (n = 0; n < msg_cnt; n++)
  574. X    if (msg_bit(list, n)) {
  575. X        wprint("%s\n", compose_hdr(n));
  576. X        /* if -/+ given, set current message pointer to this message */
  577. X        if (inc_cur_msg) {
  578. X        current_msg = n;
  579. X        /* if - was given, then set to first listed message.
  580. X         * otherwise, + means last listed message -- let it go...
  581. X         */
  582. X        if (inc_cur_msg < 0)
  583. X            inc_cur_msg = 0;
  584. X        }
  585. X    }
  586. X    return 0;
  587. X}
  588. X
  589. X/*
  590. X * Do an ls from the system.
  591. X * Read from a popen and use wprint in case the tool does this command.
  592. X * The folders command uses this command.
  593. X */
  594. ls(x, argv)
  595. char **argv;
  596. X{
  597. X    register char  *p, *tmp;
  598. X    char       buf[128];
  599. X    register FILE  *pp;
  600. X
  601. X    if (*++argv && !strcmp(*argv, "-?"))
  602. X    return help(0, "ls", cmd_help);
  603. X    if (!(p = do_set(set_options, "lister")))
  604. X    p = "";
  605. X    (void) sprintf(buf, "%s -C%s ", LS_COMMAND, p);
  606. X    p = buf+strlen(buf);
  607. X    for ( ; *argv; ++argv) {
  608. X    x = 0;
  609. X    if (**argv != '-')
  610. X        tmp = getpath(*argv, &x);
  611. X    else
  612. X        tmp = *argv;
  613. X    if (x == -1) {
  614. X        wprint("%s: %s\n", *argv, tmp);
  615. X        return -1;
  616. X    }
  617. X    p += strlen(sprintf(p, " %s", tmp));
  618. X    }
  619. X    if (!(pp = popen(buf, "r"))) {
  620. X    error(buf);
  621. X    return -1;
  622. X    }
  623. X    turnon(glob_flags, IGN_SIGS);
  624. X    while (fgets(buf, 127, pp))
  625. X    wprint(buf);
  626. X    (void) pclose(pp);
  627. X    turnoff(glob_flags, IGN_SIGS);
  628. X    return 0;
  629. X}
  630. X
  631. sh(un_used, argv)
  632. char **argv;
  633. X{
  634. X    register char *p;
  635. X    char buf[128];
  636. X
  637. X    if (istool > 1 || *++argv && !strcmp(*argv, "-?"))
  638. X    return help(0, "shell", cmd_help);
  639. X    if (!(p = do_set(set_options, "shell"))
  640. X    && !(p = do_set(set_options, "SHELL")))
  641. X    p = DEF_SHELL;
  642. X    if (!*argv)
  643. X    (void) strcpy(buf, p);
  644. X    else
  645. X    (void) argv_to_string(buf, argv);
  646. X    echo_on();
  647. X    (void) system(buf);
  648. X    echo_off();
  649. X    return 0;
  650. X}
  651. X
  652. static
  653. sorter(cmd1, cmd2)
  654. register struct cmd *cmd1, *cmd2;
  655. X{
  656. X    return strcmp(cmd1->command, cmd2->command);
  657. X}
  658. X
  659. question_mark(x, argv)
  660. char **argv;
  661. X{
  662. X    int n = 0;
  663. X    char *Cmds[50], *p, *malloc(), buf[30];
  664. X
  665. X    qsort((char *)cmds, sizeof(cmds)/sizeof(struct cmd)-1,
  666. X            sizeof(struct cmd), sorter);
  667. X
  668. X    if (!*++argv) {
  669. X    for (x = 0; cmds[x].command; x++) {
  670. X        if (!(x % 5))
  671. X        if (!(p = Cmds[n++] = malloc(80))) {
  672. X            error("malloc in question_mark()");
  673. X            free_vec(Cmds);
  674. X            return -1;
  675. X        }
  676. X        p += strlen(sprintf(p, "%-11.11s  ", cmds[x].command));
  677. X    }
  678. X    Cmds[n++] = savestr("Type: `command -?' for help with most commands.");
  679. X    Cmds[n] = NULL;
  680. X    (void) help(0, Cmds, NULL);
  681. X    free_vec(Cmds);
  682. X    } else {
  683. X    for (x = 0; cmds[x].command; x++)
  684. X        if (!strcmp(*argv, cmds[x].command))
  685. X        return cmd_line(sprintf(buf, "%s -?", *argv), msg_list);
  686. X    print("Unknown command: %s\n", *argv);
  687. X    }
  688. X    return -1;
  689. X}
  690. X
  691. X#ifdef SIGSTOP
  692. stop(argc, argv)
  693. char **argv;
  694. X{
  695. X    if (istool)
  696. X    print("Not a tool-based option.");
  697. X    if (argc && *++argv && !strcmp(*argv, "-?"))
  698. X    return help(0, "stop", cmd_help);
  699. X    if (kill(getpid(), SIGTSTP) == -1)
  700. X    error("couldn't stop myself");
  701. X    return -1;
  702. X}
  703. X#endif /* SIGSTOP */
  704. X
  705. extern char **environ;
  706. static int spaces = 0;
  707. X
  708. Setenv(i, argv)
  709. char **argv;
  710. X{
  711. X    char *newstr;
  712. X
  713. X    if (i < 2 || i > 3 || !strcmp(argv[1], "-?"))
  714. X    return help(0, "setenv", cmd_help);
  715. X
  716. X    if (i == 3) {
  717. X    newstr = malloc(strlen(argv[1]) + strlen(argv[2]) + 2);
  718. X    (void) sprintf(newstr, "%s=%s", argv[1], argv[2]);
  719. X    } else {
  720. X    newstr = malloc(strlen(argv[1]) + 2);
  721. X    (void) sprintf(newstr, "%s=", argv[1]);
  722. X    }
  723. X
  724. X    (void) Unsetenv(2, argv);
  725. X
  726. X    for (i = 0; environ[i]; i++);
  727. X    if (!spaces) {
  728. X    char **new_environ = (char **)malloc((i+2) * sizeof(char *));
  729. X    /* add 1 for the new item, and 1 for null-termination */
  730. X    if (!new_environ) {
  731. X        free(newstr);
  732. X        return -1;
  733. X    }
  734. X    spaces = 1;
  735. X    for (i = 0; new_environ[i] = environ[i]; i++);
  736. X    xfree(environ);
  737. X    environ = new_environ;
  738. X    }
  739. X    environ[i] = newstr;
  740. X    environ[i+1] = NULL;
  741. X    spaces--;
  742. X    return -1;
  743. X}
  744. X
  745. Unsetenv(n, argv)
  746. char **argv;
  747. X{
  748. X    char **envp, **last;
  749. X
  750. X    if (n != 2 || !strcmp(argv[1], "-?"))
  751. X    return help(0, "unsetenv", cmd_help);
  752. X
  753. X    n = strlen(argv[1]);
  754. X    for (last = environ; *last; last++);
  755. X    last--;
  756. X
  757. X    for (envp = environ; envp <= last; envp++) {
  758. X    if (strncmp(argv[1], *envp, n) == 0 && (*envp)[n] == '=') {
  759. X        xfree(*envp);
  760. X        *envp = *last;
  761. X        *last-- = NULL;
  762. X        spaces++;
  763. X    }
  764. X    }
  765. X    return -1;
  766. X}
  767. X
  768. Printenv()
  769. X{
  770. X    char **e = environ;
  771. X    while (*e)
  772. X    wprint("%s\n", *e++);
  773. X    return -1;
  774. X}
  775. X
  776. X/*
  777. X * internal stty call to allow the user to change his tty character
  778. X * settings.  sorry, no way to change cbreak/echo modes.  Save echo_flg
  779. X * so that execute() won't reset it.
  780. X */
  781. my_stty(un_used, argv)
  782. char **argv;
  783. X{
  784. X    u_long save_echo = ison(glob_flags, ECHO_FLAG);
  785. X
  786. X    turnon(glob_flags, ECHO_FLAG);
  787. X    execute(argv);
  788. X    if (save_echo)
  789. X    turnon(glob_flags, ECHO_FLAG);
  790. X    else
  791. X    turnoff(glob_flags, ECHO_FLAG);
  792. X
  793. X    savetty();
  794. X#ifdef TIOCGLTC
  795. X    if (ioctl(0, TIOCGLTC, <chars))
  796. X    error("TIOCGLTC");
  797. X#endif /* TIOCGLTC */
  798. X    echo_off();
  799. X    return -1;
  800. X}
  801. END_OF_FILE
  802. if test 21317 -ne `wc -c <'commands.c'`; then
  803.     echo shar: \"'commands.c'\" unpacked with wrong size!
  804. fi
  805. # end of 'commands.c'
  806. fi
  807. if test -f 'mush.h' -a "${1}" != "-c" ; then 
  808.   echo shar: Will not clobber existing file \"'mush.h'\"
  809. else
  810. echo shar: Extracting \"'mush.h'\" \(20902 characters\)
  811. sed "s/^X//" >'mush.h' <<'END_OF_FILE'
  812. X/* @(#)mush.h    (c) copyright 1986 (Dan Heller) */
  813. X
  814. X#define VERSION "Mail User's Shell (Vers 6.0) Sat Apr  2 19:36:07 PST 1988"
  815. X
  816. X#include "config.h"
  817. X
  818. X#ifdef CURSES
  819. X#ifdef USG
  820. X#    define _USG
  821. X#    undef USG
  822. X#endif /* USG */
  823. X#include <curses.h>
  824. X#if !defined(USG) && defined(_USG)
  825. X#    define USG
  826. X#    undef _USG
  827. X#endif /* USG && _USG */
  828. X#else /* CURSES */
  829. X#include <stdio.h>
  830. X#if defined(SYSV) && defined(USG)
  831. X#include <termio.h>
  832. X#endif /* SYSV && USG */
  833. X#endif /* CURSES */
  834. X
  835. X#include <ctype.h>
  836. X#include <errno.h>
  837. X#include <setjmp.h>
  838. X#include "strings.h"
  839. X
  840. X#ifdef SUNTOOL
  841. X#    include <suntool/tool_hs.h>
  842. X#else  /* SUNTOOL */
  843. X#    include <sys/types.h>
  844. X#    include <signal.h>
  845. X#    ifndef SYSV
  846. X#        include <sys/time.h>
  847. X#     include <sys/ioctl.h>   /* for ltchars */
  848. X#    else
  849. X#        include <time.h>
  850. X#        include <fcntl.h>
  851. X#    endif /* SYSV */
  852. X#endif /* SUNTOOL */
  853. X
  854. X#include <sys/stat.h>
  855. X#include <sys/file.h>
  856. X
  857. X#ifdef SUNTOOL
  858. X#    include <suntool/gfxsw.h>
  859. X#    include <suntool/panel.h>
  860. X#    include <suntool/ttysw.h>
  861. X#    include <suntool/ttytlsw.h>
  862. X#    include <suntool/menu.h>
  863. X#    include <suntool/icon_load.h>
  864. X#endif /* SUNTOOL */
  865. X
  866. X/* if no maximum number of files can be found, we'll use getdtablesize() */
  867. X#ifdef _NFILE
  868. X#    define MAXFILES _NFILE
  869. X#else
  870. X#ifdef NOFILE
  871. X#    define MAXFILES NOFILE
  872. X#endif /* NOFILE */
  873. X#endif /* NFILE */
  874. X
  875. X#ifndef CTRL
  876. X#define CTRL(c)        ('c' & 037)
  877. X#endif /* CTRL */
  878. X
  879. X#define ESC         '\033'
  880. X
  881. X#define NO_STRING    ""
  882. X#ifdef  NULL
  883. X#undef  NULL
  884. X#endif /* NULL */
  885. X#define NULL        (char *)0
  886. X#define NULL_FILE    (FILE *)0
  887. X#define DUBL_NULL    (char **)0
  888. X#define TRPL_NULL    (char ***)0
  889. X#ifdef putchar
  890. X#undef putchar
  891. X#endif /* putchar */
  892. X#define putchar(c)    fputc(c, stdout)
  893. X#define bell()         fputc('\007', stderr)
  894. X
  895. X/* For error recovery purposes, send keyboard generated signals to a special
  896. X * routine (interrupt) to set a global flag (WAS_INTR) and return to the
  897. X * calling routine which is responsible for checking the flag.  For both
  898. X * on_intr() and off_intr() macros, initialize WAS_INTR to false.
  899. X */
  900. X#define on_intr() \
  901. X    turnoff(glob_flags, WAS_INTR), oldint = signal(SIGINT, interrupt), \
  902. X    oldquit = signal(SIGQUIT, interrupt)
  903. X
  904. X#define off_intr() \
  905. X    turnoff(glob_flags, WAS_INTR), (void) signal(SIGINT, oldint), \
  906. X    (void) signal(SIGQUIT, oldquit)
  907. X
  908. X/* Don't flush input when setting echo or cbreak modes (allow typeahead) */
  909. X#ifdef TIOCSETN
  910. X#ifdef stty
  911. X#undef stty
  912. X#endif /* stty */
  913. X#define stty(fd, sgttybuf)    (ioctl(fd, TIOCSETN, sgttybuf))
  914. X#endif /* TIOCSETN */
  915. X
  916. X/* for system-V machines that run termio */
  917. X#if defined(SYSV) && defined(USG)
  918. unsigned char vmin;
  919. X#define sg_erase  c_cc[2]
  920. X#define sg_flags  c_lflag
  921. X#define sg_kill   c_cc[3]
  922. X#define sg_ospeed c_cflag
  923. X#define gtty(fd, SGTTYbuf)    ioctl(fd, TCGETA, SGTTYbuf)
  924. X#undef stty
  925. X#define stty(fd, SGTTYbuf)    ioctl(fd, TCSETAW, SGTTYbuf)
  926. X#define echon()    (_tty.sg_flags |= (ECHO|ECHOE),    stty(0, &_tty))
  927. X#define echoff()   (_tty.sg_flags &= ~ECHO,   stty(0, &_tty))
  928. X#define cbrkon()   \
  929. X    (_tty.sg_flags &= ~ICANON, _tty.c_cc[VMIN] = 1, stty(0, &_tty))
  930. X#define cbrkoff()  \
  931. X    (_tty.sg_flags |= ICANON, _tty.c_cc[VMIN] = vmin, stty(0, &_tty))
  932. X#define savetty()  (void) gtty(0, &_tty), vmin = _tty.c_cc[VMIN]
  933. X#define cbreak()   cbrkon()
  934. X#define nocbreak() cbrkoff()
  935. X
  936. X/* If curses isn't defined, declare our 'tty' and macros for echo/cbreak */
  937. X#ifndef CURSES
  938. typedef struct termio SGTTY;
  939. X#define echom()    echon()
  940. X#define noechom()  echoff()
  941. X#define crmode()   cbrkon()
  942. X#define nocrmode() cbrkoff()
  943. X
  944. X#else /* CURSES */
  945. X/* If curses is defined, use the echo/cbreak commands in library only
  946. X * if cursees is running.  If curses isn't running, use macros above.
  947. X */
  948. X#define echom()    ((iscurses) ? echo(): echon())
  949. X#define noechom()  ((iscurses) ? noecho(): echoff())
  950. X#define crmode()   ((iscurses) ? cbreak() : cbrkon())
  951. X#define nocrmode() ((iscurses) ? nocbreak() : cbrkoff())
  952. X#endif /* CURSES */
  953. X#endif /* SYSV && USG */
  954. X
  955. X#if !defined(USG)
  956. X#ifndef CURSES
  957. X/* if curses is not defined, simulate the same tty based macros */
  958. typedef struct sgttyb SGTTY;
  959. X/* Do real ioctl calls to set the tty modes */
  960. X#define crmode()   (_tty.sg_flags |= CBREAK,  stty(0, &_tty))
  961. X#define nocrmode() (_tty.sg_flags &= ~CBREAK, stty(0, &_tty))
  962. X#define echom()    (_tty.sg_flags |= ECHO,    stty(0, &_tty))
  963. X#define noechom()  (_tty.sg_flags &= ~ECHO,   stty(0, &_tty))
  964. X#define savetty()  (void) gtty(0, &_tty)
  965. X#else /* CURSES */
  966. X#define echom()    echo()
  967. X#define noechom()  noecho()
  968. X#endif /* ~CURSES */
  969. X#endif /* ~USG */
  970. X
  971. X/* With all that out of the way, we can now declare our tty type */
  972. SGTTY _tty;
  973. X
  974. X/* These macros now turn on/off echo/cbreak independent of the UNIX running */
  975. X#define echo_on()    \
  976. X    if (_tty.sg_flags && isoff(glob_flags, ECHO_FLAG)) nocrmode(), echom()
  977. X#define echo_off()    \
  978. X    if (_tty.sg_flags && isoff(glob_flags, ECHO_FLAG)) crmode(), noechom()
  979. X
  980. X#define strdup(dst, src) (xfree (dst), dst = savestr(src))
  981. X#define Debug        if (debug) printf
  982. X
  983. X#ifdef SYSV
  984. X#ifndef L_SET
  985. X#define L_SET    0
  986. X#endif /* L_SET */
  987. X#ifndef F_OK
  988. X#define F_OK    000
  989. X#define R_OK    004
  990. X#define W_OK    002
  991. X#define E_OK    001
  992. X#endif /* F_OK */
  993. typedef    unsigned long    u_long;
  994. X#define vfork   fork
  995. X#ifdef SIGCHLD
  996. X#undef SIGCHLD
  997. X#endif /* SIGCHLD */
  998. X#define SIGCHLD SIGCLD
  999. X#endif /* SYSV */
  1000. X
  1001. X#if !defined(SUNTOOL) && !defined(CURSES)
  1002. X
  1003. X#define TRUE          1
  1004. X#define FALSE          0
  1005. X#define print          printf
  1006. X#define wprint          printf
  1007. X#define print_more      printf
  1008. X
  1009. X#endif /* SUNTOOL && !CURSES */
  1010. X
  1011. X#ifndef max
  1012. X#define max(a,b) (((a) > (b)) ? (a) : (b))
  1013. X#define min(a,b) (((a) < (b)) ? (a) : (b))
  1014. X#endif /* max */
  1015. X
  1016. X#if defined(CURSES) && !defined(SUNTOOL)
  1017. X#define wprint printf
  1018. X#endif /* !SUNTOOL && CURSES */
  1019. X
  1020. X#if defined(CURSES) || defined(SUNTOOL)
  1021. X#define print_more      turnon(glob_flags, CONT_PRNT), print
  1022. void print();        /* printf to window or curses or tty accordingly */
  1023. X#endif /* CURSES || SUNTOOL */
  1024. X
  1025. X#ifdef  SUNTOOL
  1026. X
  1027. X#define NO_ITEM          (Panel_item)0
  1028. X#define NO_EVENT      (struct inputevent *)0
  1029. X#define TIME_OUT      60           /* sleep 60 secs between mailchecks */
  1030. X#define PIX_XOR          PIX_SRC ^ PIX_DST
  1031. X#define ID           event.ie_code
  1032. X#define l_width(font)      fonts[font]->pf_defaultsize.x /* width of letter */
  1033. X#define l_height(font)      fonts[font]->pf_defaultsize.y /* height of letter */
  1034. X#define Clrtoeol(w,x,y,f) pw_text(w, x, y, PIX_SRC, fonts[f], blank)
  1035. X#define type_cursor(op)   pw_char(msg_win, txt.x,txt.y, op, fonts[curfont],'_')
  1036. X
  1037. X#define highlight(win,x,y,font,s) \
  1038. X    pw_text(win,x,y, PIX_SRC, fonts[font],s), \
  1039. X    pw_text(win,x+1,y, \
  1040. X    (ison(glob_flags, REV_VIDEO))? PIX_NOT(PIX_SRC): PIX_SRC|PIX_DST, \
  1041. X    fonts[font],s)
  1042. X
  1043. X/* Fonts */
  1044. X#define FONTDIR          "/usr/lib/fonts/fixedwidthfonts"
  1045. X#define DEFAULT          0
  1046. X#define SMALL           1
  1047. X#define LARGE           2
  1048. X#define MAX_FONTS      3
  1049. X
  1050. X#endif /* SUNTOOL */
  1051. X
  1052. X/* bits and pieces */
  1053. X#define turnon(flg,val)   ((flg) |= ((u_long)1 << ((u_long)(val)-1L)))
  1054. X#define turnoff(flg,val)  ((flg) &= ~((u_long)1 << ((u_long)(val)-1L)))
  1055. X#define ison(flg,val)     ((u_long)(flg) & ((u_long)1 << ((u_long)(val)-1L)))
  1056. X#define isoff(flg,val)    (!ison((flg), (val)))
  1057. X#define set_replied(n)      \
  1058. X    if (isoff(msg[n].m_flags, REPLIED)) \
  1059. X        turnon(glob_flags, DO_UPDATE), turnon(msg[n].m_flags, REPLIED)
  1060. X#define set_isread(n)      \
  1061. X    if (ison(msg[n].m_flags, UNREAD)) \
  1062. X        turnon(glob_flags, DO_UPDATE), turnoff(msg[n].m_flags, UNREAD)
  1063. X
  1064. X/* msg lists represented by bits (8 should be replaced by sizeof(char) */
  1065. X#define clear_msg_list(list)      (void) bzero(list, (msg_cnt+7)/8)
  1066. X#define msg_bit(list, n)    ((list[(n) / 8] >> ((n) % 8)) & 1)
  1067. X#define set_msg_bit(list, n)    (list[(n) / 8] |= (1 << ((n) % 8)))
  1068. X#define unset_msg_bit(list, n)  (list[(n) / 8] &= ~(1 << ((n) % 8)))
  1069. X#define bput(S1, S2, Len, op)                   \
  1070. X        {                         \
  1071. X            register char *s1 = S1, *s2 = S2;         \
  1072. X            register int len = Len;             \
  1073. X            while(len--)                 \
  1074. X            *s2++ op *s1++;             \
  1075. X        }
  1076. X#define bitput(m1,m2,len,op)    bput(m1, m2, (((len)+7)/8), op)
  1077. X
  1078. X/* convenience and/or readability */
  1079. X#define when          break;case
  1080. X#define otherwise      break;default
  1081. X#define lower(c)      (isupper(c)? tolower(c): c)
  1082. X#define Lower(c)      (c = lower(c))
  1083. X#define upper(c)      (islower(c)? toupper(c): c)
  1084. X#define Upper(c)      (c = upper(c))
  1085. X#define skipspaces(n)     for(p += (n); *p == ' ' || *p == '\t'; ++p)
  1086. X#define skipdigits(n)     for(p += (n); isdigit(*p); ++p)
  1087. X
  1088. X#define NO_FLG        0
  1089. X
  1090. X/* various flags */
  1091. long   glob_flags;    /* global boolean flags thruout the whole program */
  1092. X#define DO_UPDATE   1    /* check for changes to avoid unnecessary copyback */
  1093. X#define REV_VIDEO   2    /* reverse video for curses or toolmode */
  1094. X#define CONT_PRNT   3    /* continue to print (maybe a printf) without a '\n' */
  1095. X#define DO_SHELL    4    /* run a shell even if no mail? (true if tool) */
  1096. X#define DO_PIPE     5    /* true if commands are piping to another command */
  1097. X#define IS_PIPE     6    /* true if commands' "input" is piped from another */
  1098. X#define IGN_SIGS    7    /* true if catch() should not longjump */
  1099. X#define IGN_BANG    8    /* ignore ! as a history reference (see source()) */
  1100. X#define ECHO_FLAG   9    /* if true, echo|cbreak is ON, echo typing (-e) */
  1101. X#define IS_GETTING 10    /* true if we're getting input for a letter */
  1102. X#define PRE_CURSES 11    /* true if curses will be run, but hasn't started yet */
  1103. X#define READ_ONLY  12    /* -r passed to folder() (or main) setting read only */
  1104. X#define REDIRECT   13    /* true if stdin is being redirected */
  1105. X#define WAS_INTR   14    /* catch interrupts, set this flag (signals.c) */
  1106. X#define WARNING    15   /* if set, various warning messages may be printed */
  1107. X#define NEW_MAIL   17   /* new mail has arrived; user is busy or in icon mode */
  1108. X#define CNTD_CMD   18   /* curses.c -- "...continue..." prompt in curses */
  1109. X#define IS_SENDING 19   /* was started to send mail, not to be run as a shell */
  1110. X#define MIL_TIME   20    /* if $mil_time is set, use 24hr military time fmt */
  1111. X
  1112. X#define VERBOSE        1       /* verbose flag for sendmail */
  1113. X#define INCLUDE        2       /* include msg in response */
  1114. X#define INCLUDE_H    3    /* include msg with header */
  1115. X#define EDIT        4    /* enter editor by defualt on mailing */
  1116. X#define SIGN        5    /* auto-include ~/.signature in mail */
  1117. X#define DO_FORTUNE    6    /* add a fortune at end of msgs */
  1118. X
  1119. X/* msg flags */
  1120. X#define NO_HEADER    7    /* don't print header of message (top, write) */
  1121. X#define DELETE        8
  1122. X#define OLD            9
  1123. X#define UNREAD        10
  1124. X#define UPDATE_STATUS    11    /* change status of msg when copyback */
  1125. X#define NO_PAGE        12    /* don't page this message */
  1126. X#define INDENT        13    /* indent included msg with string */
  1127. X#define NO_IGNORE    14    /* don't ignore headers */
  1128. X#define PRESERVE    15      /* preserve in mailbox unless deleted */
  1129. X#define TOP        15    /* just print the top of msg (same as pre) */
  1130. X#define FORWARD        16    /* Forward messages into the message buffer */
  1131. X#define REPLIED        17    /* Messages that have been replied to */
  1132. X#define NEW_SUBJECT    18    /* new subject regardless of $ask (mail -s) */
  1133. X
  1134. X#define    MAXMSGS_BITS    MAXMSGS/sizeof(char)    /* number of bits for bitmap */
  1135. X
  1136. struct msg {
  1137. X    u_long m_flags;
  1138. X    long   m_offset;               /* offset in tempfile of msg */
  1139. X    long   m_size;                 /* number of bytes in msg */
  1140. X    int    m_lines;                /* number of lines in msg */
  1141. X} msg[MAXMSGS];
  1142. X
  1143. struct options {
  1144. X    char *option;
  1145. X    char *value;
  1146. X    struct options *next;
  1147. X} *set_options, *aliases, *ignore_hdr, *functions, *fkeys, *own_hdrs;
  1148. X#ifdef CURSES
  1149. struct options *bindings;
  1150. X#endif /* CURSES */
  1151. X
  1152. struct cmd {
  1153. X    char *command;
  1154. X    int (*func)();
  1155. X};
  1156. extern struct cmd ucb_cmds[];
  1157. extern struct cmd cmds[], hidden_cmds[];
  1158. X#ifdef SUNTOOL
  1159. extern struct cmd fkey_cmds[];
  1160. X#endif /* SUNTOOL */
  1161. X
  1162. FILE
  1163. X    *tmpf,        /* temporary holding place for all mail */
  1164. X    *open_file(),    /* open a file or program for write/append */
  1165. X    *popen();        /* this should be in stdio.h */
  1166. X
  1167. extern char
  1168. X    *sys_errlist[],    /* system's list of global error messages */
  1169. X#ifdef SUNTOOL
  1170. X    *font_files[],     /* the names of the files fonts are kept in */
  1171. X    *alt_fonts[],     /* fonts to use if first ones don't work */
  1172. X#endif /* SUNTOOL */
  1173. X    **environ;        /* user's environment variables */
  1174. X
  1175. extern int errno;    /* global system error number */
  1176. jmp_buf jmpbuf;        /* longjmp to jmpbuf on sigs (not in tool) */
  1177. X
  1178. char
  1179. X    debug,        /* debug causes various print statements in code */
  1180. X    tempfile[40],    /* path to filename of temporary file */
  1181. X    msg_list[MAXMSGS_BITS],    /* MAXMSGS bits of boolean storage */
  1182. X    *cmd_help,        /* filename of location for "command -?" commands. */
  1183. X    *get_name_n_addr(), /* get name and addr from a well-formed address */
  1184. X    *login,        /* login name of user */
  1185. X    *mailfile,        /* path to filename of current mailfile */
  1186. X    *ourname[MAX_HOST_NAMES],    /* the name and aliases of the current host */
  1187. X    *prompt,        /* the prompt string -- may have %d */
  1188. X    *escape,        /* the "tilde escape" when inputting text to letter */
  1189. X    *hdrs_only,        /* true if -H flag was given --set to args */
  1190. X    *hdr_format,    /* set to the header format string; referenced a lot */
  1191. X    *argv_to_string(),    /* convert a vector of strings into one string */
  1192. X    **make_command(),    /* build a command vector (argv) */
  1193. X    **mk_argv(),    /* given a string, make a vector */
  1194. X    *itoa(),        /* return a string representation of a number */
  1195. X    *lcase_strcpy(),    /* just like strcpy, but convert all chars to lower */
  1196. X    *variable_stuff(),    /* return information about variables */
  1197. X    *no_newln(),    /* remove newline and extra whitespace - return end */
  1198. X    *savestr(),        /* strcpy arg into malloc-ed memory; return address */
  1199. X    *spoolfile,        /* MAILDIR/$USER in a string -- this is used a lot */
  1200. X    *date_to_string(),    /* returns a string described by parse_date() */
  1201. X    *msg_date(),    /* return a string of the date of a message */
  1202. X    *parse_date(),    /* parse an ascii date, and return message-id str */
  1203. X    *Time(),        /* returns string expression of time (takes args) */
  1204. X    *do_range(),    /* parse a string converting to a "range" of numbers */
  1205. X    *getpath(),        /* static char returning path (expanding ~, +, %, #) */
  1206. X    *compose_hdr(),    /* returns a formatted line describing passed msg # */
  1207. X    *my_atoi(),     /* do an atoi, but return the last char parsed */
  1208. X    *do_set(),        /* set/unset an option, alias, ignored-hdr */
  1209. X    *reply_to(),    /* who do we reply to when responding */
  1210. X    *reply_hdr(),    /* compose In-Reply-to: hdr according to format */
  1211. X    *cc_to(),         /* when responding, return str which is the cc-list */
  1212. X    *subject_to(),      /* when responding, return str which is the subject */
  1213. X    *header_field(),    /* the line in msg described by arg (message header) */
  1214. X    *alias_to_address(),/* convert a name[list] to "real" names */
  1215. X    *set_header(),     /* [interactive] proc to set/display to/subject/cc */
  1216. X    *getenv(), *prog_name;
  1217. X
  1218. int
  1219. X    last_msg_cnt,    /* when checking for new mail, save the last msg_cnt */
  1220. X    msg_cnt,        /* total number of messages */
  1221. X    crt,        /* min number of lines msg contains to invoke pager */
  1222. X    current_msg,    /* the current message we're dealing with */
  1223. X    exec_pid,        /* pid of a command that has been "exec"ed */
  1224. X    hist_no,        /* command's history number */
  1225. X    iscurses,        /* if we're running curses */
  1226. X    istool,        /* argv[0] == "xxxxtool", ranges from 0 to 2 */
  1227. X    n_array[128],    /* array of message numbers in the header window */
  1228. X    screen,        /* number of headers window can handle */
  1229. X
  1230. X    quit(), cleanup(), catch(), do_alias(), respond(), cd(), sh(), stop(),
  1231. X    folder(), save_msg(), delete(), do_mail(), lpr(), alts(), set(), do_hdrs(),
  1232. X    rm_edfile(), pick(), save_opts(), preserve(), sort(), readmsg(),
  1233. X    do_pick(), print_help(), folders(), question_mark(), do_from(), my_stty(),
  1234. X    do_version(), disp_hist(), source(), do_echo(), sigchldcatcher(), ls(),
  1235. X    nopenfiles(), Setenv(), Unsetenv(), Printenv(), bus_n_seg(), msg_flags(),
  1236. X    toggle_debug(), stop_start(), interrupt();
  1237. X
  1238. long
  1239. X    still_more,        /* there is still more message to display */
  1240. X    spool_size,        /* size of sppol mail regardless of current folder */
  1241. X    last_size,        /* the lastsize of the mailfile since last check */
  1242. X    time();        /* satisfy lint */
  1243. X
  1244. void
  1245. X    xfree(), free_vec(), error(), getmail(), mail_status(),
  1246. X    file_to_fp(), init(), display_msg();
  1247. X    /* printf(), fclose(), fflush(), fputs(), fputc() */
  1248. X#ifdef TIOCGLTC
  1249. struct ltchars ltchars;            /* tty character settings */
  1250. X#endif /* TIOCGLTC */
  1251. X
  1252. X#ifdef CURSES
  1253. X
  1254. X#define STANDOUT(y,x,s) standout(), mvaddstr(y,x,s), standend()
  1255. X#define redraw()    clearok(curscr, TRUE), wrefresh(curscr)
  1256. X
  1257. int
  1258. X    curses_init(),    /* interpret commands via the curses interface */
  1259. X    bind_it();        /* bind chars or strings to functions */
  1260. X#endif /* CURSES */
  1261. X
  1262. X#ifdef SUNTOOL
  1263. void
  1264. X    lock_cursors(), unlock_cursors(), scroll_win(),
  1265. X    set_fkeys(), set_key(), toggle_opt(), help_opt();
  1266. X
  1267. char
  1268. X    *rite(),        /* rite a char to msg_win: return string if c == '\n' */
  1269. X    *find_key(),    /* pass x,y coords to find which function key assoc. */
  1270. X    *key_set_to(),    /* pass fkey string, return string describing func */
  1271. X    *panel_get(),          /* returns what has been typed in a panel item */
  1272. X    *tool_help,        /* help for tool-related things (sometimes, overlap) */
  1273. X    blank[128];        /* use to clear to end of line */
  1274. X
  1275. int
  1276. X    time_out,        /* time out interval to wait for new mail */
  1277. X    rootfd,        /* the root window's fd */
  1278. X    parentfd,        /* the parent's window fd */
  1279. X    getting_opts,    /* true if getting/setting opts from msg_win */
  1280. X    curfont,        /* the current font to use for mail message window */
  1281. X    total_fonts,    /* total number of fonts available */
  1282. X    get_hdr_field,    /* bitmask of header fields to be gotten */
  1283. X
  1284. X    msg_io(), msgwin_handlesigwinch(), hdr_io(), hdrwin_handlesigwinch(),
  1285. X    sigchldcatcher(), sigtermcatcher(), sigwinchcatcher(), do_sort(),
  1286. X    do_compose(), do_edit(), read_mail(), delete_mail(), respond_mail(),
  1287. X    do_hdr(), display_hdrs(), print_sigwinch(), p_set_opts(),
  1288. X    tool_mgmt(), do_help(), text_done(), msg_num_done(), do_lpr(),
  1289. X    toolquit(), change_font(), do_clear(), do_update(),
  1290. X    file_dir(), do_file_dir(), do_send(), abort_mail(), check_new_mail(),
  1291. X    fkey_cmd(), fkey_settings();
  1292. X
  1293. struct tchars  tchars;            /* more tty character settings */
  1294. X
  1295. struct tool *tool;      /* main tool structure */
  1296. struct toolsw
  1297. X    *panel_sw,        /* main panel subwindow */
  1298. X    *hdr_sw,         /* subwindow for message headers */
  1299. X    *hdr_panel_sw,    /* panel for headers */
  1300. X    *tty_sw,         /* subwindow which forks a shell (usually editor) */
  1301. X    *print_sw,         /* subwindow for print statements */
  1302. X    *msg_sw;         /* main subwindow to display messages and more */
  1303. X
  1304. struct pixwin
  1305. X    *msg_win,        /* main pixwin for message display and more */
  1306. X    *hdr_win,        /* pixwin for message headers */
  1307. X    *print_win;        /* pixwin for printing messages ( print() ) */
  1308. X
  1309. struct pr_pos txt;               /* current position of text written */
  1310. struct rect msg_rect, hdr_rect;         /* sizes of the main and hdr rects */
  1311. struct pixfont *fonts[MAX_FONTS];    /* array of fonts */
  1312. X
  1313. Panel
  1314. X    main_panel,        /* the main panel dealing with generic items */
  1315. X    hdr_panel;        /* panel which contains message header specific items */
  1316. X
  1317. Panel_item
  1318. X    abort_item,        /* abort mail in progress */
  1319. X    alias_item,        /* set/view/change current mail aliases */
  1320. X    cd_item,        /* changes file_item to cd (for cd-ing) */
  1321. X    comp_item,        /* compose a letter */
  1322. X    delete_item,    /* delete/undelete messages */
  1323. X    edit_item,        /* edit a message */
  1324. X    font_item,        /* choose which font to use */
  1325. X    folder_item,    /* change folders */
  1326. X    file_item,         /* text item for files or directories (forlder/cd) */
  1327. X    hdr_display,    /* format message headers are displayed */
  1328. X    help_item,        /* choose this to get various help */
  1329. X    ignore_item,    /* set/view/change message headers to be ignored */
  1330. X    input_item,        /* text item to get values for set/unsetting values */
  1331. X    msg_num_item,    /* text item to explicity state which message to read */
  1332. X    next_scr,        /* display the next screenful of message headers */
  1333. X    option_item,    /* set/view/unset mail options */
  1334. X    prev_scr,        /* display the previous screen of messages */
  1335. X    print_item,        /* send current message to the printer */
  1336. X    quit_item,        /* quit tool/close to icon */
  1337. X    read_item,        /* read the current message */
  1338. X    respond_item,    /* respond to messages */
  1339. X    save_item,        /* saves messages; uses text item input_item */
  1340. X    send_item,        /* when composing letter, this will send it off */
  1341. X    sort_item,        /* sort routine... */
  1342. X    sub_hdr_item[6],    /* display items that just sit there and give help */
  1343. X    update_item;    /* commit changes to folder */
  1344. X
  1345. struct itimerval mail_timer;    /* frequency to check for new mail */
  1346. X
  1347. X            /* mouse symbols and data */
  1348. X/* left, middle and right mouse pixrects */
  1349. struct cursor
  1350. X    l_cursor, m_cursor, r_cursor, coffee, read_cursor, write_cursor,
  1351. X    main_cursor, checkmark;
  1352. X
  1353. struct pixrect *msg_pix; /* pixrect holding text of a message */
  1354. extern struct pixrect mouse_left, mouse_middle, mouse_right;
  1355. extern struct pixrect dn_arrow, up_arrow, cycle, shade_50;
  1356. X
  1357. extern struct icon mail_icon;
  1358. X#endif /* SUNTOOL */
  1359. X
  1360. END_OF_FILE
  1361. if test 20902 -ne `wc -c <'mush.h'`; then
  1362.     echo shar: \"'mush.h'\" unpacked with wrong size!
  1363. fi
  1364. # end of 'mush.h'
  1365. fi
  1366. echo shar: End of archive 8 \(of 14\).
  1367. cp /dev/null ark8isdone
  1368. MISSING=""
  1369. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  1370.     if test ! -f ark${I}isdone ; then
  1371.     MISSING="${MISSING} ${I}"
  1372.     fi
  1373. done
  1374. if test "${MISSING}" = "" ; then
  1375.     echo You have unpacked all 14 archives.
  1376.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1377. else
  1378.     echo You still need to unpack the following archives:
  1379.     echo "        " ${MISSING}
  1380. fi
  1381. ##  End of shell archive.
  1382. exit 0
  1383.